/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package uk.ac.rdg.resc.mmd.diva;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import uk.ac.rdg.resc.mmd.utils.ClientHttpRequest;

/**
 *
 * @author Alastair
 */
public class DivaWebService {

    private String divaBaseUrl;

    private final int corrolationLength = 20;
    private final int signalNoiseRatio = 1;
    private final int latBinWidthDegrees = 3;
    private final int lonBinWidthDegrees = 2;

    public DivaWebService(String divaBaseUrl) {
        this.divaBaseUrl = divaBaseUrl;
    }

    public HashMap<String, String> upload(InputStream is, String fileName) throws IOException, JDOMException {
        ClientHttpRequest httpRequest = new ClientHttpRequest(this.divaBaseUrl + "/upload");
        httpRequest.setParameter("data", fileName, is);
        InputStream inputStream = httpRequest.post();
        return uploadHelper(inputStream);
    }

    public HashMap<String, String> upload(String inputFile) throws JDOMException, IOException {

        ClientHttpRequest httpRequest = new ClientHttpRequest(this.divaBaseUrl + "/upload");
        httpRequest.setParameter("data", new File(inputFile));
        InputStream inputStream = httpRequest.post();
        return uploadHelper(inputStream);
    }

    private HashMap<String, String> uploadHelper(InputStream inputStream) throws IOException, JDOMException {

        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer xml = new StringBuffer();
        String line = null;
        while((line = in.readLine()) != null) {
            xml.append(line);
        }
        String xmlResponse = xml.toString();

        Element rootElement = getXmlRootElement(xmlResponse);
        List<Element> children = rootElement.getChildren();

        int obsCount = 0;
        String sessionId = null;
        double x0, x1, y0, y1;
        x0 = x1 = y0 = y1 = Double.NaN;

        for (int iChild = 0; iChild < children.size(); iChild++) {
            Element child = children.get(iChild);
            String idAttribute = child.getAttributeValue("id");
            String childText = child.getTextTrim();
            System.out.println("idAttribute: " + idAttribute + ", childText: " + childText);
            if (idAttribute.equals("obs_count")) {
                obsCount = Integer.parseInt(childText);
            } else if (idAttribute.equals("obs_x0")) {
                x0 = Double.parseDouble(childText);
            } else if (idAttribute.equals("obs_x1")) {
                x1 = Double.parseDouble(childText);
            } else if (idAttribute.equals("obs_y0")) {
                y0 = Double.parseDouble(childText);
            } else if (idAttribute.equals("obs_y1")) {
                y1 = Double.parseDouble(childText);
            } else if (idAttribute.equals("sessionid")) {
                sessionId = childText;
            }
        }

        System.out.println("Session ID: " + sessionId);
        System.out.println("Obs Count: " + obsCount);
        System.out.println("x0 / x1: " + x0 + " / " + x1);
        System.out.println("y0 / y1: " + y0 + " / " + y1);

        HashMap<String, String> returnParams = new HashMap<String, String>();
        returnParams.put("sessionId", sessionId);
        returnParams.put("bbox", x0 + "," + y0 + "," + x1 + "," + y1);

        return returnParams;
    }

    public String interpolate(String sessionId, String bbox) throws MalformedURLException, IOException, JDOMException {

        String[] bboxIndices = bbox.split(",");

        URL analysisUrl  = new URL(this.divaBaseUrl + "/make_analysis" +
                "?sessionid=" + sessionId +
                "&len=" + this.corrolationLength +
                "&stn=" + this.signalNoiseRatio +
                "&dx=" + this.lonBinWidthDegrees +
                "&dy=" + this.latBinWidthDegrees +
                "&x0=" + bboxIndices[0] +
                "&y0=" + bboxIndices[1] +
                "&x1=" + bboxIndices[2] +
                "&y1=" + bboxIndices[3]);

        InputStream inputStream = analysisUrl.openStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer xml = new StringBuffer();
        String line = null;
        while((line = reader.readLine()) != null) {
            xml.append(line);
        }
        String xmlResponse = xml.toString();
        System.out.println(xmlResponse);

        Element rootElement = getXmlRootElement(xmlResponse);
        Element result = rootElement.getChild("result");
        String fieldname = result.getAttributeValue("src");

        System.out.println("src: " + fieldname);

        return fieldname;
    }

    public InputStream streamWMSMap(String fieldname, String bbox) throws MalformedURLException, IOException {

        String urlString = this.divaBaseUrl + "/diva_on_web" +
                "?LAYERS=" + fieldname + "%23analyzed_field" +
                "&TRANSPARENT=true" +
                "&FORMAT=" + "image%2Fpng" +
                "&STYLES=method%3Apcolor_flat%2Bncontours%3A40%2Binverted%3Afalse%2Bcmap%3Ajet%2Bvmin%3A-5.43691%2Bvmax%3A30.0554" +
                "&SERVICE=WMS" +
                "&VERSION=1.1.1" +
                "&REQUEST=GetMap" +
                "&EXCEPTIONS=application%2Fvnd.ogc.se_inimage" +
                "&SRS=EPSG%3A4326" +
                "&BBOX=" + bbox +
                "&WIDTH=512" +
                "&HEIGHT=256";

        URL wmsUrl  = new URL(urlString);
        InputStream wmsInputStream = wmsUrl.openStream();
        return wmsInputStream;
    }

    public InputStream streamNetcdf(String fieldname) throws IOException {
        URL ncUrl = new URL(this.divaBaseUrl + "/download" +
                "?fieldname=" + fieldname);
        return ncUrl.openStream();
    }

    public void downloadNetcdf(String fieldname, String outFileName) throws MalformedURLException, IOException {
        URL ncUrl = new URL(this.divaBaseUrl + "/download" +
                "?fieldname=" + fieldname);
        InputStream ncInputStream = ncUrl.openStream();
        FileOutputStream fos = new FileOutputStream(outFileName);

        byte[] buf = new byte[32 * 1024]; // 32k buffer
        int nRead = 0;
        while( (nRead = ncInputStream.read(buf)) != -1 ) {
            fos.write(buf, 0, nRead);
        }
        fos.flush();
        fos.close();
    }

    private Element getXmlRootElement(String xmlResponse) throws JDOMException, IOException {
        SAXBuilder builder = new SAXBuilder();
        Reader stringReader = new StringReader(xmlResponse);
        Document doc = builder.build(stringReader);
        return doc.getRootElement();
    }

}
